package com.longe.netty.transferFiles.server;

import com.alibaba.fastjson.JSON;
import com.longe.netty.transferFiles.domain.*;
import com.longe.netty.transferFiles.util.CacheUtil;
import com.longe.netty.transferFiles.util.FileUtil;
import com.longe.netty.transferFiles.util.MsgUtil;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.channel.socket.SocketChannel;

public class MyServerHandler extends ChannelInboundHandlerAdapter {

    /**
     * 当客户端主动链接服务端的链接后，这个通道就是活跃的了。也就是客户端与服务端建立了通信通道并且可以传输数据
     */
    @Override
    public void channelActive(ChannelHandlerContext ctx) {
        SocketChannel channel = (SocketChannel) ctx.channel();
        System.err.println("客户端连接成功,其IP:" + channel.localAddress().getHostString());
    }

    /**
     * 当客户端主动断开服务端的链接后，这个通道就是不活跃的。也就是说客户端与服务端的关闭了通信通道并且不可以传输数据
     */
    @Override
    public void channelInactive(ChannelHandlerContext ctx) {
        System.err.println("客户端断开链接" + ctx.channel().localAddress().toString());
    }

    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //数据格式验证
        if (!(msg instanceof FileTransferProtocol)) return;

        FileTransferProtocol fileTransferProtocol = (FileTransferProtocol) msg;
        //0传输文件'请求'、1文件传输'指令'、2文件传输'数据'
        switch (fileTransferProtocol.getTransferType()) {
            case 0:
                TransferRequest transferRequest = (TransferRequest) fileTransferProtocol.getTransferObj();

                //断点续传信息，实际应用中需要将断点续传信息保存到数据库中
                TransferInstruct existTransferInstruct = CacheUtil.transferInstruct.get(transferRequest.getFileName());
                if (null != existTransferInstruct) {
                    if (existTransferInstruct.getFileTransferStatus() == TransferConstants.FileStatus.COMPLETE) {
                        //传输完成删除断点信息
                        CacheUtil.transferInstruct.remove(transferRequest.getFileName());
                        System.err.println("已经传输完成...");
                        return;
                    }
                    System.err.println("接收客户端传输文件请求[断点续传]。" + JSON.toJSONString(existTransferInstruct));
                    ctx.writeAndFlush(MsgUtil.buildTransferInstruct(existTransferInstruct));
                } else {
                    //发送信息
                    FileTransferProtocol sendFileTransferProtocol = MsgUtil
                            .buildTransferInstruct(TransferConstants.FileStatus.BEGIN, transferRequest.getFileUrl(), 0);
                    ctx.writeAndFlush(sendFileTransferProtocol);
                    System.err.println("接收客户端传输文件请求。" + JSON.toJSONString(transferRequest));
                }
                break;
            case 2:
                TransferData transferData = (TransferData) fileTransferProtocol.getTransferObj();
                TransferInstruct transferInstruct = FileUtil.writeFile("D:\\test\\bbb", transferData);

                //保存断点续传信息
                CacheUtil.transferInstruct.put(transferData.getFileName(), transferInstruct);

                ctx.writeAndFlush(MsgUtil.buildTransferInstruct(transferInstruct));
                System.err.println("接收客户端传输文件数据。" + JSON.toJSONString(transferData));

                //传输完成删除断点信息
                if (transferInstruct.getFileTransferStatus() == TransferConstants.FileStatus.COMPLETE) {
                    CacheUtil.transferInstruct.remove(transferData.getFileName());
                }
                break;
            default:
                break;
        }

    }

    /**
     * 抓住异常，当发生异常的时候，可以做一些相应的处理，比如打印日志、关闭链接
     */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        ctx.close();
        System.err.println("异常信息：\r\n" + cause.getMessage());
    }

}